package com.zyc.studentstudy.utils

import kotlinx.coroutines.suspendCancellableCoroutine
import java.util.concurrent.CancellationException
import kotlin.coroutines.Continuation
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException

/**
 * Created by zhangyuncai on 2025/7/8.
 * 描述：挂起函数
 */
class SimpleAwait {
    private var continuation: Continuation<Unit>? = null

    /**
     * 等待事件发生，挂起当前协程直到[onEvent]被调用
     * @return 事件发生时传递的值
     */
    suspend fun await() {
        suspendCancellableCoroutine<Unit> { cont ->
            // 确保同一时间只有一个等待者
            check(continuation == null) { "Already have a waiting coroutine" }

            continuation = cont.apply {
                // 当协程被取消时自动清理
                invokeOnCancellation {
                    continuation = null
                }
            }
        }
    }

    /**
     * 触发事件并恢复等待的协程
     * @param value 要传递给等待协程的值
     */
    fun onEvent() {
        continuation?.resume(Unit)?.also {
            continuation = null
        }
    }

    /**
     * 取消当前等待的协程
     * @param cause 可选的取消原因
     */
    fun cancel(cause: Throwable? = null) {
        continuation?.resumeWithException(
            cause ?: CancellationException("SimpleAwait was cancelled")
        )
        continuation = null
    }

    /**
     * 检查当前是否有协程在等待
     */
    val isWaiting: Boolean get() = continuation != null
}

/**
 * 一个简单的挂起/恢复机制实现，允许协程等待某个事件发生
 *
 * @param T 期待的事件结果类型
 * @property continuation 存储当前的挂起协程的续体
 * @property isWaiting 表示当前是否有协程在等待
 */
class SimpleValueAwait<T : Any> {
    private var continuation: Continuation<T>? = null

    /**
     * 等待事件发生，挂起当前协程直到[onEvent]被调用
     * @return 事件发生时传递的值
     */
    suspend fun await(): T {
        return suspendCancellableCoroutine { cont ->
            // 确保同一时间只有一个等待者
            check(continuation == null) { "Already have a waiting coroutine" }

            continuation = cont.apply {
                // 当协程被取消时自动清理
                invokeOnCancellation {
                    continuation = null
                }
            }
        }
    }

    /**
     * 触发事件并恢复等待的协程
     * @param value 要传递给等待协程的值
     */
    fun onEvent(value: T) {
        continuation?.resume(value)?.also {
            continuation = null
        }
    }

    /**
     * 取消当前等待的协程
     * @param cause 可选的取消原因
     */
    fun cancel(cause: Throwable? = null) {
        continuation?.resumeWithException(
            cause ?: CancellationException("SimpleAwait was cancelled")
        )
        continuation = null
    }

    /**
     * 检查当前是否有协程在等待
     */
    val isWaiting: Boolean get() = continuation != null
}